"""Support for Node-RED discovery."""

import logging
from typing import Any

from homeassistant.components.websocket_api.connection import ActiveConnection
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import (
    async_dispatcher_connect,
    async_dispatcher_send,
)

from .const import (
    CONF_BINARY_SENSOR,
    CONF_BUTTON,
    CONF_COMPONENT,
    CONF_NODE_ID,
    CONF_NUMBER,
    CONF_REMOVE,
    CONF_SELECT,
    CONF_SENSOR,
    CONF_SERVER_ID,
    CONF_SWITCH,
    CONF_TEXT,
    CONF_TIME,
    DOMAIN,
    DOMAIN_DATA,
    NODERED_DISCOVERY,
    NODERED_DISCOVERY_NEW,
    NODERED_DISCOVERY_UPDATED,
)

SUPPORTED_COMPONENTS = [
    CONF_BINARY_SENSOR,
    CONF_BUTTON,
    CONF_NUMBER,
    CONF_SELECT,
    CONF_SENSOR,
    CONF_SWITCH,
    CONF_TEXT,
    CONF_TIME,
]

_LOGGER = logging.getLogger(__name__)

ALREADY_DISCOVERED = "already_discovered"
CHANGE_ENTITY_TYPE = "change_entity_type"
PLATFORMS_LOADED = "platforms_loaded"
DISCOVERY_DISPATCHED = "discovery_dispatched"


async def start_discovery(hass: HomeAssistant, hass_config: dict) -> bool:
    """Initialize of Node-RED Discovery."""

    async def async_device_message_received(
        msg: dict[str, Any], connection: ActiveConnection
    ) -> None:
        """Process the received message."""
        component = msg[CONF_COMPONENT]
        server_id = msg[CONF_SERVER_ID]
        node_id = msg[CONF_NODE_ID]

        if component not in SUPPORTED_COMPONENTS:
            _LOGGER.warning("Integration %s is not supported", component)
            return

        discovery_hash = f"{DOMAIN}-{server_id}-{node_id}"
        data = hass_config

        _LOGGER.debug("Discovery message: %s", msg)

        if ALREADY_DISCOVERED not in data:
            data[ALREADY_DISCOVERED] = set()

        # Check if already discovered
        already_discovered = discovery_hash in data[ALREADY_DISCOVERED]

        if already_discovered:
            log_text = "Removing" if CONF_REMOVE in msg else "Updating"

            _LOGGER.info("%s %s %s %s", log_text, component, server_id, node_id)

            async_dispatcher_send(
                hass, NODERED_DISCOVERY_UPDATED.format(discovery_hash), msg, connection
            )
        else:
            # Add component - ensure platform is set up first
            _LOGGER.info("Creating %s %s %s", component, server_id, node_id)

            data[ALREADY_DISCOVERED].add(discovery_hash)

            async_dispatcher_send(
                hass, NODERED_DISCOVERY_NEW.format(component), msg, connection
            )

    hass.data[DOMAIN_DATA][DISCOVERY_DISPATCHED] = async_dispatcher_connect(
        hass,
        NODERED_DISCOVERY,
        async_device_message_received,
    )


def stop_discovery(hass: HomeAssistant) -> None:
    """Remove discovery dispatcher."""
    hass.data[DOMAIN_DATA][DISCOVERY_DISPATCHED]()
